trait Printer {
    fn print_file(&self);
}

struct Epson {}

struct Hp {}

impl Printer for Hp {
    fn print_file(&self) {
        println!("printer hp")
    }
}

impl Printer for Epson {
    fn print_file(&self) {
        println!("printer epson")
    }
}

//=========

trait Computer {
    fn print(&self);
    fn set_printer(&mut self, p: Box<dyn Printer>);
}

struct Mac {
    printer: Box<dyn Printer>,
}

struct Windows {
    printer: Box<dyn Printer>,
}

impl Computer for Windows {
    fn print(&self) {
        self.printer.print_file();
    }

    fn set_printer(&mut self, p: Box<dyn Printer>) {
        self.printer = p;
    }
}

impl Computer for Mac {
    fn print(&self) {
        self.printer.print_file();
    }

    fn set_printer(&mut self, p: Box<dyn Printer>) {
        self.printer = p;
    }
}

#[test]
fn main() {
    let hp = Hp {};
    let epson = Epson {};

    let mut mac = Mac { printer: Box::new(hp) };
    mac.print();
    mac.set_printer(Box::new(epson));
    mac.print();
}